#include "spline.h"
#include "mycanvas.h"
#include <QVector2D>

spLine::spLine(QList<QVector2D> nodos, int _n)
{
    this->nodos=nodos;
    this->n = _n;
    this->z = new double[n+1];
    this->obtenerZs();
    this->calcularFunciones();
}

spLine::~spLine()
{
    delete z;
    delete h;
    delete A;
    delete B;
    delete C;
}

void spLine::calcularFunciones()
{
    this->A = new double[n];
    this->B = new double[n];
    this->C = new double[n];
    for(int i=0; i< this->n ;i++)
    {
        this->A[i] = calcA(i);
        this->B[i] = calcB(i);
        this->C[i] = calcC(i);
    }
}
void spLine::obtenerZs()
{
    this->h = new double[this->n];
    double b[this->n];
    double u[this->n];
    double v[this->n];
    for(int i=0; i<= this->n-1 ;i++)
    {

        this->h[i] = this->nodos[i+1].toPoint().x() - this->nodos[i].toPoint().x();
        b[i] = (6 * (this->nodos[i+1].toPoint().y() - this->nodos[i].toPoint().y())) / this->h[i];
    }
    u[1] = 2 * (this->h[0] + this->h[1]);
    v[1] = b[1] - b[0];

    for(int i=2; i<= this->n-1 ;i++)
    {
        u[i] = 2 * (this->h[i] + this->h[i-1]) - ((this->h[i-1] * this->h[i-1]) - 1) / u[i-1];
        v[i] = b[i] - b[i-1] - ((this->h[i-1] * v[i-1]) / u[i-1]);
    }
    z[this->n] = 0.0;

    for(int i=this->n - 1; i > 0 ;i--)
    {
       this->z[i]=(v[i] - this->h[i]*z[i+1]) / u[i];
    }
    z[0] = 0.0;
}
double spLine::evaluarSi(double x)
{
    int i = 0;
    for(int j=this->n-1; j> 0;j--)
    {
        if (x - this->nodos[j].toPoint().x()>0){
            i = j;
            break;
        }
    }
    return this->nodos[i].toPoint().y() +(x - this->nodos[i].toPoint().x())*(this->C[i]+(x - this->nodos[i].toPoint().x())*(this->B[i] + (x - this->nodos[i].toPoint().x()) * this->A[i]));
}
double spLine::calcA(int i)
{
    return (1/(6*this->h[i])) * (this->z[i+1] - this->z[i]);
}
double spLine::calcB(int i)
{
    return this->z[i]/2;
}
double spLine::calcC(int i)
{
    return -((this->h[i]/6) * this->z[i+1]) - ((this->h[i]/3) * this->z[i]) + ((1/this->h[i]) * (this->nodos[i+1].toPoint().y()-this->nodos[i].toPoint().y()));
}
void spLine::pintarFuncion(MyCanvas* canvas)
{
    QPainter painter(canvas);
    painter.setPen(Qt::blue);
    for(int i=this->nodos.first().toPoint().x();i<=this->nodos.last().toPoint().x();i++)
    {
        double x1=i-1;

        double x2=i;

        double y1=this->evaluarSi(x1);
        double y2=this->evaluarSi(x2);
        painter.drawLine(x1,y1, x2,y2);
    }
}
